//! 配置管理模块

use crate::{Error, Result};
use serde::{Deserialize, Serialize};
use std::path::Path;

/// 完整的数据库配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Config {
    /// 数据库配置
    pub database: crate::config::DatabaseConfig,
    /// 网络配置
    pub network: NetworkConfig,
    /// 日志配置
    pub logging: LoggingConfig,
    /// 性能配置
    pub performance: PerformanceConfig,
}

impl Default for Config {
    fn default() -> Self {
        Self {
            database: crate::config::DatabaseConfig::default(),
            network: NetworkConfig::default(),
            logging: LoggingConfig::default(),
            performance: PerformanceConfig::default(),
        }
    }
}

impl Config {
    /// 从文件加载配置
    pub fn from_file<P: AsRef<Path>>(path: P) -> Result<Self> {
        let content = std::fs::read_to_string(path)
            .map_err(|e| Error::config(format!("读取配置文件失败: {}", e)))?;
        
        let config: Config = toml::from_str(&content)
            .map_err(|e| Error::config(format!("解析配置文件失败: {}", e)))?;
        
        config.validate()?;
        Ok(config)
    }
    
    /// 保存配置到文件
    pub fn save_to_file<P: AsRef<Path>>(&self, path: P) -> Result<()> {
        let content = toml::to_string_pretty(self)
            .map_err(|e| Error::config(format!("序列化配置失败: {}", e)))?;
        
        std::fs::write(path, content)
            .map_err(|e| Error::config(format!("写入配置文件失败: {}", e)))?;
        
        Ok(())
    }
    
    /// 验证配置
    pub fn validate(&self) -> Result<()> {
        // 验证内存限制
        if self.database.memory_limit == 0 {
            return Err(Error::config("内存限制不能为0"));
        }
        
        // 验证页面大小
        if self.database.page_size == 0 || !self.database.page_size.is_power_of_two() {
            return Err(Error::config("页面大小必须是2的幂"));
        }
        
        // 验证缓冲池大小
        if self.database.buffer_pool_size > self.database.memory_limit {
            return Err(Error::config("缓冲池大小不能超过内存限制"));
        }
        
        // 验证网络端口
        if self.network.postgres_port == 0 || self.network.http_port == 0 {
            return Err(Error::config("端口号不能为0"));
        }
        
        if self.network.postgres_port == self.network.http_port {
            return Err(Error::config("PostgreSQL端口和HTTP端口不能相同"));
        }
        
        // 验证最大连接数
        if self.database.max_connections == 0 {
            return Err(Error::config("最大连接数不能为0"));
        }
        
        Ok(())
    }
}

/// 网络配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NetworkConfig {
    /// PostgreSQL端口
    pub postgres_port: u16,
    /// HTTP端口
    pub http_port: u16,
    /// 绑定地址
    pub bind_address: String,
    /// 启用TLS
    pub enable_tls: bool,
    /// TLS证书路径
    pub tls_cert_path: Option<String>,
    /// TLS私钥路径
    pub tls_key_path: Option<String>,
}

impl Default for NetworkConfig {
    fn default() -> Self {
        Self {
            postgres_port: 5432,
            http_port: 8080,
            bind_address: "127.0.0.1".to_string(),
            enable_tls: false,
            tls_cert_path: None,
            tls_key_path: None,
        }
    }
}

/// 日志配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LoggingConfig {
    /// 日志级别
    pub level: String,
    /// 日志格式
    pub format: LogFormat,
    /// 日志输出目标
    pub target: LogTarget,
    /// 日志文件路径
    pub file_path: Option<String>,
    /// 日志文件最大大小（字节）
    pub max_file_size: Option<u64>,
    /// 保留的日志文件数量
    pub max_files: Option<u32>,
}

impl Default for LoggingConfig {
    fn default() -> Self {
        Self {
            level: "info".to_string(),
            format: LogFormat::Text,
            target: LogTarget::Stdout,
            file_path: None,
            max_file_size: Some(100 * 1024 * 1024), // 100MB
            max_files: Some(10),
        }
    }
}

/// 日志格式
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum LogFormat {
    Text,
    Json,
}

/// 日志输出目标
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum LogTarget {
    Stdout,
    Stderr,
    File,
    Both,
}

/// 性能配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PerformanceConfig {
    /// 工作线程数
    pub worker_threads: Option<usize>,
    /// 启用查询缓存
    pub enable_query_cache: bool,
    /// 查询缓存大小
    pub query_cache_size: usize,
    /// 启用统计信息收集
    pub enable_statistics: bool,
    /// 统计信息更新间隔（秒）
    pub statistics_update_interval: u64,
    /// 启用慢查询日志
    pub enable_slow_query_log: bool,
    /// 慢查询阈值（毫秒）
    pub slow_query_threshold_ms: u64,
}

impl Default for PerformanceConfig {
    fn default() -> Self {
        Self {
            worker_threads: None, // 使用系统默认
            enable_query_cache: true,
            query_cache_size: 64 * 1024 * 1024, // 64MB
            enable_statistics: true,
            statistics_update_interval: 300, // 5分钟
            enable_slow_query_log: true,
            slow_query_threshold_ms: 1000, // 1秒
        }
    }
}

/// 配置构建器
#[derive(Debug)]
pub struct ConfigBuilder {
    config: Config,
}

impl ConfigBuilder {
    /// 创建新的配置构建器
    pub fn new() -> Self {
        Self {
            config: Config::default(),
        }
    }
    
    /// 设置内存限制
    pub fn memory_limit(mut self, limit: usize) -> Self {
        self.config.database.memory_limit = limit;
        self
    }
    
    /// 设置最大连接数
    pub fn max_connections(mut self, max: usize) -> Self {
        self.config.database.max_connections = max;
        self
    }
    
    /// 设置PostgreSQL端口
    pub fn postgres_port(mut self, port: u16) -> Self {
        self.config.network.postgres_port = port;
        self
    }
    
    /// 设置HTTP端口
    pub fn http_port(mut self, port: u16) -> Self {
        self.config.network.http_port = port;
        self
    }
    
    /// 设置绑定地址
    pub fn bind_address(mut self, address: String) -> Self {
        self.config.network.bind_address = address;
        self
    }
    
    /// 设置日志级别
    pub fn log_level(mut self, level: String) -> Self {
        self.config.logging.level = level;
        self
    }
    
    /// 构建配置
    pub fn build(self) -> Result<Config> {
        self.config.validate()?;
        Ok(self.config)
    }
}

impl Default for ConfigBuilder {
    fn default() -> Self {
        Self::new()
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use tempfile::NamedTempFile;
    
    #[test]
    fn test_default_config() {
        let config = Config::default();
        assert!(config.validate().is_ok());
    }
    
    #[test]
    fn test_config_validation() {
        let mut config = Config::default();
        
        // 测试无效的内存限制
        config.database.memory_limit = 0;
        assert!(config.validate().is_err());
        
        // 恢复有效值
        config.database.memory_limit = 1024 * 1024 * 1024;
        
        // 测试无效的页面大小
        config.database.page_size = 1000; // 不是2的幂
        assert!(config.validate().is_err());
        
        // 恢复有效值
        config.database.page_size = 8192;
        
        // 测试相同的端口
        config.network.postgres_port = 8080;
        config.network.http_port = 8080;
        assert!(config.validate().is_err());
    }
    
    #[test]
    fn test_config_builder() {
        let config = ConfigBuilder::new()
            .memory_limit(2 * 1024 * 1024 * 1024) // 2GB
            .max_connections(500)
            .postgres_port(5433)
            .http_port(8081)
            .bind_address("0.0.0.0".to_string())
            .log_level("debug".to_string())
            .build()
            .unwrap();
        
        assert_eq!(config.database.memory_limit, 2 * 1024 * 1024 * 1024);
        assert_eq!(config.database.max_connections, 500);
        assert_eq!(config.network.postgres_port, 5433);
        assert_eq!(config.network.http_port, 8081);
        assert_eq!(config.network.bind_address, "0.0.0.0");
        assert_eq!(config.logging.level, "debug");
    }
    
    #[test]
    fn test_config_file_operations() {
        let config = Config::default();
        let temp_file = NamedTempFile::new().unwrap();
        
        // 保存配置
        config.save_to_file(temp_file.path()).unwrap();
        
        // 加载配置
        let loaded_config = Config::from_file(temp_file.path()).unwrap();
        
        // 验证配置相同
        assert_eq!(config.database.memory_limit, loaded_config.database.memory_limit);
        assert_eq!(config.network.postgres_port, loaded_config.network.postgres_port);
    }
}
